/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse.gui.query;

import com.gwtext.client.widgets.Panel;
import nfse.gui.client.*;
import com.gwtext.client.data.*;
import com.gwtext.client.core.*;

import com.gwtext.client.widgets.*;
import com.gwtext.client.widgets.form.*;
import com.gwtext.client.widgets.layout.*;
import com.gwtext.client.data.SimpleStore;
import com.gwtext.client.data.Store;
import com.gwtext.client.widgets.event.ButtonListenerAdapter;
import com.gwtext.client.widgets.form.event.*;
import com.google.gwt.core.client.GWT;
import com.gwtext.client.widgets.grid.*;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import nfse.gui.util.*;


//public class SearchPanel extends com.google.gwt.user.client.ui.FlexTable
public class SearchPanel extends Panel {
    NetFSEClient client = null;

    SearchAnalysisTab searchAnalysisTab;

    final Button searchBtn = new Button("Search");

    final Button resetBtn = new Button("Reset");

    final TextArea notes = new TextArea("Notes", "Notes");

    final DateField startDate = new DateField("Start Date", "Y-m-d");

    final DateField endDate = new DateField("End Date", "Y-m-d");

    final TimeField startTime = new TimeField();

    final TimeField endTime = new TimeField();

    final NumberField recordLimit = new NumberField("Record Limit Per Type", "Record Limit Per Type");

    final FieldSet ipListSearchFS = new FieldSet("IP List Search");

    final TextArea ipListTA = new TextArea("IP List", "ipList");

    final ComboBox cb1 = new ComboBox();

    FieldSet searchCriteriaFS = new FieldSet("Search Criteria");

    final TextField desIPStart = new TextField("Destination IP", "destinationIP");

    final TextField desIPEnd = new TextField("And", "destinationIP");

    final TextField srcIPStart = new TextField("Source IP", "sourceIP");

    final TextField srcIPEnd = new TextField("And", "sourceIP");

    final NumberField desPortStart = new NumberField("Destination Port", "destinationPort");

    final NumberField desPortEnd = new NumberField("And", "destinationPort");

    String searchOriginPoint = "Source & Destination";

    Checkbox[] typeCB;

    private int[] types = new int[0];

    int[] typeIdxs;

    String[] typeNames;

    private GridPanel typeGrid = new GridPanel();

    CheckboxSelectionModel cbSelectionModel = new CheckboxSelectionModel();

    public SearchPanel(NetFSEClient client) {
        this.client = client;
        this.setTitle("Search");
        this.setLayout(new com.gwtext.client.widgets.layout.FitLayout());
        client.checkIfReadyToBuild(this);
    }

    public SearchPanel(NetFSEClient client, SearchAnalysisTab searchAnalysisTab) {
        this.client = client;
        this.searchAnalysisTab = searchAnalysisTab;
        this.setTitle("Search");
        this.setLayout(new com.gwtext.client.widgets.layout.FitLayout());
        // searchAnalysisTab.checkIfReadyToBuild(this);
    }

    public void buildPanel() {
        Panel panel = new Panel();
        panel.setLayout(new BorderLayout());
        panel.setBorder(true);

        // create the FormPanel and set the label position to top
        FormPanel formPanel = new FormPanel();
        formPanel.setLabelAlign(Position.RIGHT);
        formPanel.setBorder(false);
        formPanel.setBodyStyle("background-color:#EAF1FE;");

        // create top panel with ColumnLayout
        Panel topPanel = new Panel();
        topPanel.setLayout(new ColumnLayout());
        topPanel.setBodyStyle("background-color:#EAF1FE;");

        // create first panel and add fields to it
        Panel columnOnePanel = new Panel();

        columnOnePanel.setLayout(new TableLayout(3));
        columnOnePanel.setPaddings(0, 10, 0, 0);
        columnOnePanel.setBodyStyle("background-color:#EAF1FE;padding: 5;");

        // startTime.setHideLabel(true);
        endTime.setHideLabel(true);
        startTime.setWidth(80);
        endTime.setWidth(80);
        startDate.setAllowBlank(false);
        // startDate.setFormat("Y-m-d");

        startTime.setFormat("H:i:s");
        // endDate.setFormat("Y-m-d");
        endTime.setFormat("H:i:s");

        Panel startDateTimeLabelPanel = new Panel();
        startDateTimeLabelPanel.setBodyStyle("background-color:#EAF1FE;padding: 5;text-align: right;");
        Label startDateTime = new Label("Start Date:");
        startDateTimeLabelPanel.setBorder(false);
        startDateTime.setStyle("font-size: 8pt;");
        startDateTimeLabelPanel.add(startDateTime);
        columnOnePanel.add(startDateTimeLabelPanel);

        Panel startDateTimePanel = new Panel();
        startDateTimePanel.setLayout(new HorizontalLayout(1));
        startDateTimePanel.setBodyStyle("background-color:#EAF1FE;padding: 5;");
        startDateTimePanel.add(startDate);
        startDateTimePanel.add(startTime);
        columnOnePanel.add(startDateTimePanel, new TableLayoutData(2));

        Panel endDateTimeLabelPanel = new Panel();
        endDateTimeLabelPanel.setBodyStyle("background-color:#EAF1FE;padding: 5;text-align: right;");
        endDateTimeLabelPanel.setBorder(false);
        Label endDateTime = new Label("End Date:");
        endDateTime.setStyle("font-size: 8pt;");
        endDateTimeLabelPanel.add(endDateTime);
        columnOnePanel.add(endDateTimeLabelPanel);

        Panel endDateTimePanel = new Panel();
        endDateTimePanel.setLayout(new HorizontalLayout(1));
        endDateTimePanel.setBodyStyle("background-color:#EAF1FE;padding: 5;");
        endDateTimePanel.add(endDate);
        endDateTimePanel.add(endTime);
        columnOnePanel.add(endDateTimePanel, new TableLayoutData(2));

        columnOnePanel.add(new Label(""));
        columnOnePanel.add(createTypeGrid(), new TableLayoutData(2));

        recordLimit.setWidth(80);
        recordLimit.setValue(1000000);
        recordLimit.setMinValue(0);
        recordLimit.setMaxValue(10000000);

        ToolTip recordLimitTT = new ToolTip("Leave This Field Blank For Unlimited Number of Records");
        recordLimitTT.applyTo(recordLimit);

        Label rl = new Label("Record Limit Per Type:");
        rl.setStyle("font-size: 8pt;");
        Panel rlLabelPanel = new Panel();
        rlLabelPanel.setBodyStyle("background-color:#EAF1FE;padding: 5;text-align: right;");
        rlLabelPanel.setBorder(false);
        rlLabelPanel.add(rl);
        columnOnePanel.add(rlLabelPanel);

        Panel rlP = new Panel();
        rlP.setBodyStyle("background-color:#EAF1FE;padding: 5;");
        rlP.setBorder(false);
        rlP.add(recordLimit);
        columnOnePanel.add(rlP, new TableLayoutData(2));

        Panel notesLabelPanel = new Panel();
        notesLabelPanel.setBodyStyle("background-color:#EAF1FE;padding: 5;text-align: right;");
        notesLabelPanel.setBorder(false);
        Label notesL = new Label("Notes:");
        notesL.setStyle("font-size: 8pt;");

        notesLabelPanel.add(notesL);
        columnOnePanel.add(notesLabelPanel);

        notes.setWidth(200);
        notes.setHeight(100);

        Panel notesPanel = new Panel();
        notesPanel.setBodyStyle("background-color:#EAF1FE;padding: 5;");
        notesPanel.setBorder(false);
        notesPanel.add(notes);

        columnOnePanel.add(notesPanel, new TableLayoutData(2));

        // add first panel as first column with 50% of the width
        topPanel.add(columnOnePanel, new ColumnLayoutData(.50));

        // create second panel and add fields to it

        TabPanel column2 = new TabPanel();
        column2.setBorder(false);
        Panel search1 = new Panel();
        search1.setLayout(new TableLayout(1));
        search1.setTitle("IP Search");
        search1.setBodyStyle("background-color:#EAF1FE;padding: 5;");
        search1.setAutoHeight(true);
        search1.setBorder(false);
        // search1.setHeight(400);

        ipListTA.setWidth(150);
        ipListTA.setHeight(100);

        Label ipListL = new Label("IP List");
        ipListL.setStyle("font-size: 8pt;");

        Panel ipListPanel = new Panel();
        ipListPanel.setBodyStyle("border: 0;background-color:#EAF1FE;padding: 5;margin: 5;text-align: right;");
        ipListPanel.setLayout(new VerticalLayout(2));

        ipListPanel.add(ipListL);
        ipListPanel.add(ipListTA);

        search1.add(ipListPanel);

        Label ipCBL = new Label("IP Filter");
        ipCBL.setStyle("font-size: 8pt;");

        Store store = new SimpleStore(new String[] { "originType", "type" }, new String[][] {
                new String[] { "Source & Destination", "Source & Destination" }, new String[] { "Source", "Source" },
                new String[] { "Destination", "Destination" } });
        cb1.setStore(store);
        cb1.setFieldLabel("Point Type");
        cb1.setDisplayField("originType");
        cb1.setEmptyText("Enter point");
        cb1.setEditable(false);
        cb1.setValue("Source & Destination");
        cb1.setWidth(150);

        cb1.addListener(new ComboBoxListenerAdapter() {
            public void onSelect(ComboBox comboBox, Record record, int index) {
                searchOriginPoint = record.getAsString("originType");
                System.out.println("The selected search is " + searchOriginPoint);
            }
        });

        Panel ipFilterPanel = new Panel();
        ipFilterPanel.setBodyStyle("border: 0;background-color:#EAF1FE;margin: 5;padding: 5;");
        ipFilterPanel.setLayout(new VerticalLayout(2));

        ipFilterPanel.add(ipCBL);
        ipFilterPanel.add(cb1);

        search1.add(ipFilterPanel);

        // desIPStart.setRegex("(\\[0-9]{1,3})\\.(\[0-9]{1,3})\\.(\[0-9]{1,3})\.(\[0-9]{1,3}");
        desIPStart.setRegex("(\\d{1,3}\\.){3}\\d{1,3}$");
        desPortStart.setMinValue(0);
        desPortStart.setMaxValue(65535);
        desPortEnd.setMinValue(0);
        desPortEnd.setMaxValue(65535);

        Panel search2 = new Panel();
        search2.setAutoHeight(true);
        search2.setBorder(false);
        search2.setBodyStyle("background-color:#EAF1FE;");
        search2.setPaddings(5, 5, 5, 5);
        search2.setTitle("Search Criteria");
        search2.setLayout(new VerticalLayout(2));

        Label desIPStartLBL = new Label("Destination IP Start");
        desIPStartLBL.setStyle("font-size: 8pt;");
        Label desIPEndLBL = new Label("Destination IP End *");
        desIPEndLBL.setStyle("font-size: 8pt;");
        Label srcIPStartLBL = new Label("Source IP Start");
        srcIPStartLBL.setStyle("font-size: 8pt;");
        Label srcIPEndLBL = new Label("Source IP End *");
        srcIPEndLBL.setStyle("font-size: 8pt;");
        Label desPortStartLBL = new Label("Destination Port Start");
        desPortStartLBL.setStyle("font-size: 8pt;");
        Label desPortEndLBL = new Label("Destination Port End *");
        desPortEndLBL.setStyle("font-size: 8pt;");

        Label optionalLBL = new Label("* Optional: To get a range, enter an End value");
        optionalLBL.setStyle("font-size: 7pt;");

        search2.add(desIPStartLBL);
        search2.add(desIPStart);
        search2.add(desIPEndLBL);
        search2.add(desIPEnd);
        search2.add(srcIPStartLBL);
        search2.add(srcIPStart);
        search2.add(srcIPEndLBL);
        search2.add(srcIPEnd);
        search2.add(desPortStartLBL);
        search2.add(desPortStart);
        search2.add(desPortEndLBL);
        search2.add(desPortEnd);
        search2.add(optionalLBL);

        column2.add(search1);
        column2.add(search2);

        topPanel.add(column2, new ColumnLayoutData(0.50));
        formPanel.add(topPanel);

        Panel buttonPanel = new Panel();
        buttonPanel.setBaseCls("search-button-panel");
        searchBtn.addListener(new ButtonListenerAdapter() {
            public void onClick(Button button, com.gwtext.client.core.EventObject e) {

                if (startDate.getText().length() == 0) {
                    MessageBox.alert("Please enter a Start Date");
                    return;
                }

                if (ipListTA.getText().length() == 0 && desIPStart.getText().length() == 0
                        && srcIPStart.getText().length() == 0 && desPortStart.getText().length() == 0) {
                    MessageBox
                            .alert("Enter either a IP(s) in the IP list or a specific IP as a destination and/or src and/or a Port as a destination");
                    return;
                }

                int[] localTypes = getTypes();
                if ((localTypes == null) || (localTypes.length == 0)) {
                    MessageBox.alert("You must select at least one type. Please do that then search again");
                    return;
                }

                MessageBox.alert("Search in progress. Your results will return shortly.");
                query();
            }
        });

        buttonPanel.addButton(searchBtn);
        buttonPanel.addButton(resetBtn);
        buttonPanel.setButtonAlign(Position.CENTER);
        formPanel.add(buttonPanel);

        panel.add(formPanel, new BorderLayoutData(com.gwtext.client.core.RegionPosition.CENTER));
        this.add(panel);
    }

    public void query() {
        
        String query = generateQuery();
        System.out.println(query);
        
        // final String note = notes.getText();
        QueryServiceAsync NetFSEService = (QueryServiceAsync) GWT.create(QueryService.class);

        ServiceDefTarget endpoint = (ServiceDefTarget) NetFSEService;
        endpoint.setServiceEntryPoint(NetFSEClient.QUERY_URL);

        // final QueryOptions qo = getQueryOptions();

        AsyncCallback callback = new AsyncCallback() {
            public void onFailure(Throwable caught) {
                saveQueryOptions(null);
            }

            public void onSuccess(Object result) {
                String resultStr = (String) result;
                String queryID = resultStr;
                saveQueryOptions(queryID);
                client.openQuery(queryID, types);
            }
        };

        int[] types = getTypes();
        
        // NetFSEService.query(query, this.getNote(), types, this.getLimit(),
        // -1, callback);
        NetFSEService.query(query, this.getNote(), types, 100000, -1, callback);
    }

    private String getNote() {
        String temp = this.notes.getText().trim();
        temp = NetUtil.convertToHex(temp);
        if (temp.length() > 0)
            return temp;
        return "";
    }

    private QueryOptions getQueryOptions() {
        // int[] types = getTypes();
        QueryOptions qo = new QueryOptions();
        qo.note = getNote();
        
        qo.ipSearchType = GUIUtil.IP_SEARCH_AS_BOTH;
        // if (this.asSrcRadioButton.isChecked())
        // qo.ipSearchType = GUIUtil.IP_SEARCH_AS_SRC;
        // else if (this.asDstRadioButton.isChecked())
        // qo.ipSearchType = GUIUtil.IP_SEARCH_AS_DST;

        qo.queryType = GUIUtil.QUERY_TYPE_IPS;
        // if (this.searchCriteriaRadioButton.isChecked())
        // qo.queryType = GUIUtil.QUERY_TYPE_SEARCH;
        // else if (this.payloadRadioButton.isChecked())
        // qo.queryType = GUIUtil.QUERY_TYPE_PAYLOAD;

        if (startDate.getRawValue().length() > 0) {
            qo.startTS = startDate.getRawValue();
            if (startTime.getText().length() > 0) {
                qo.startTS += " " + startTime.getText();
            }
        }
        if (endDate.getRawValue().length() > 0) {
            qo.endTS = endDate.getRawValue();
            if (endTime.getText().length() > 0) {
                qo.endTS += " " + endTime.getText();
            }
        }
        
        if (desIPStart.getText().length() > 0)
            qo.dstIP1 = desIPStart.getText();
        if (desIPEnd.getText().length() > 0)
            qo.dstIP2 = desIPEnd.getText();
        if (srcIPStart.getText().length() > 0)
            qo.srcIP1 = srcIPStart.getText();
        if (srcIPEnd.getText().length() > 0)
            qo.srcIP2 = srcIPEnd.getText();
        if (desPortStart.getText().length() > 0)
            qo.dstPort1 = Integer.parseInt(desPortStart.getText());
        if (desPortEnd.getText().length() > 0)
            qo.dstPort2 = Integer.parseInt(desPortEnd.getText());
        if (ipListTA.getText().length() > 0) {
            qo.ips = ipListTA.getText();
            qo.ips.replaceAll("\n", " ");
        }

        int[] localTypes = getTypes();
        for (int x = 0; x < localTypes.length; x++) {
            qo.setType(localTypes[x], true);
        }

        return qo;
    }

    private void saveQueryOptions(String queryID) {

        QueryServiceAsync NetFSEService = (QueryServiceAsync) GWT.create(QueryService.class);

        ServiceDefTarget endpoint = (ServiceDefTarget) NetFSEService;
        endpoint.setServiceEntryPoint(NetFSEClient.QUERY_URL);

        AsyncCallback callback = new AsyncCallback() {
            public void onFailure(Throwable caught) {
                NetFSEClient.redirect("NetFSEClient.html");
            }

            public void onSuccess(Object result) {
                client.queryHistory();
            }
        };

        QueryOptions options = getQueryOptions();
        options.queryID = queryID;
        NetFSEService.saveQueryOptions(options, callback);

    }

    public void setSearchCriteria(QueryOptions options) {
        notes.setValue(options.note);
        startDate.setValue(options.startTS);
        if ((options.endTS != null) && (options.endTS.length() > 0))
            endDate.setValue(options.endTS);
        recordLimit.setValue(options.limit);
        if ((options.ips != null) && (options.ips.length() > 0))
            ipListTA.setValue(options.ips);
        int[] selectedTypes = options.getTypes();

        for (int x = 0; x < selectedTypes.length; x++) {
            // cbSelectionModel.selectRecords(record)
        }

        if ((options.dstIP1 != null) && (options.dstIP1.length() > 0))
            desIPStart.setValue(options.dstIP1);
        if ((options.dstIP2 != null) && (options.dstIP2.length() > 0))
            desIPEnd.setValue(options.dstIP1);
        if ((options.srcIP1 != null) && (options.srcIP1.length() > 0))
            desIPStart.setValue(options.dstIP1);
        if ((options.srcIP2 != null) && (options.srcIP2.length() > 0))
            desIPEnd.setValue(options.dstIP1);
        if (options.dstPort1 > 0)
            desPortStart.setValue(options.dstPort1);
        if (options.dstPort2 > 0)
            desPortEnd.setValue(options.dstPort2);

    }

    public int[] getTypes() {
        Record[] records = cbSelectionModel.getSelections();
        int[] temp = new int[records.length];
        for (int x = 0; x < records.length; x++) {
            Record record = records[x];
            temp[x] = new Integer(record.getAsString("TypeId")).intValue();
        }
        types = temp;
        return temp;
    }

    // public void setTypes(TypeInfo typeInfo) {
    // int numTypes = typeInfo.getNumTypes();
    // this.typeCB = new Checkbox[numTypes];
    // this.types = new int[numTypes];
    // this.typeIdxs = new int[numTypes];
    // this.typeNames = new String[numTypes];
    // int maxType = -1;
    // int[] types = typeInfo.getTypes();
    // for (int i = 0; i < numTypes; i++) {
    // typeCB[i] = new Checkbox(typeInfo.getTypeName(types[i]));
    // if (maxType < types[i])
    // maxType = types[i];
    // }
    //
    // this.typeIdxs = new int[maxType + 1];
    // for (int i = 0; i < numTypes; i++) {
    // final int type = types[i];
    // final int typeIdx = i;
    // typeIdxs[type] = i;
    //
    // this.types[i] = type;
    // this.typeNames[i] = typeInfo.getTypeName(types[i]);
    //
    // final String tempTypeName = this.typeNames[i];
    // }
    //
    // }

    private String generateQuery() {

        String query = "<Query>";

        if (ipListTA.getText().length() != 0) {
            String ips = ipListTA.getText().replaceAll("\n", " ");

            String[] ipArray = ips.split(" +");

            for (int i = 0; i < ipArray.length; i++) {
                ipArray[i] = ipArray[i].trim();
                String[] ips2 = ipArray[i].split("\\.");

                if (ips2.length == 4) {

                    if ((searchOriginPoint.equals("Source & Destination")) || (searchOriginPoint.equals("Destination")))
                        query += "<Query dstip=\"" + ipArray[i] + "\"/>";
                    if ((searchOriginPoint.equals("Source & Destination")) || (searchOriginPoint.equals("Source")))
                        query += "<Query srcip=\"" + ipArray[i] + "\"/>";
                } else if (ips2.length < 4) {
                    String ip1 = "";
                    String ip2 = "";
                    for (int x = 0; x < ips2.length; x++) {
                        if (x > 0) {
                            ip1 += ".";
                            ip2 += ".";
                        }
                        ip1 += ips2[x];
                        ip2 += ips2[x];
                    }
                    for (int x = 0; x < 4 - ips2.length; x++) {
                        ip1 += ".0";
                        ip2 += ".255";
                    }
                    // alert(ip1 + ", " + ip2);
                    if ((searchOriginPoint.equals("Source & Destination")) || (searchOriginPoint.equals("Source")))
                        query += "<Query srcip=\"" + ip1 + "~" + ip2 + "\"/>";
                    if ((searchOriginPoint.equals("Source & Destination")) || (searchOriginPoint.equals("Destination")))
                        query += "<Query dstip=\"" + ip1 + "~" + ip2 + "\"/>";
                } else {
                    // invalid ip
                }
            }
        } else {
            query += "<Query ";
            String val = desIPStart.getText().trim();
            if (val.length() > 0) {
                // System.out.println("Val: '" + val + "'");
                String val2 = desIPEnd.getText().trim();
                if (val2.length() > 0) {
                    query += "dstip=\"" + val + "~" + val2 + "\" ";
                }
                // Use the following only if searching on a start ip
                // else if (!pred.equals("between"))
                // {
                // query += "dstip=\"" + pred + val + "\" ";
                // }
            }
            val = srcIPStart.getText().trim();
            if (val.length() > 0) {
                String val2 = srcIPEnd.getText().trim();
                if (val2.length() > 0) {
                    query += "srcip=\"" + val + "~" + val2 + "\" ";
                }
                // Use the following only if searching on a start ip
                // else if (!pred.equals("between")) {
                // query += "srcip=\"" + pred + val + "\" ";
                // }

            }
            val = desPortStart.getText().trim();
            if (val.length() > 0) {
                String val2 = desPortEnd.getText().trim();
                if (val2.length() > 0) {
                    if (Integer.parseInt(val) > Integer.parseInt(val2)) {
                        // alert("Invalid port range. Lower bound (" + val + ")
                        // greater than upper bound (" + val2 + ").");
                    }
                    query += "dstport=\"" + val + "~" + val2 + "\" ";
                }
                // Use the following only if searching on a start port
                // else if (!pred.equals("between"))
                // {
                // query += "dstport=\"" + pred + val + "\" ";
                // }
            }
            query += "/>";

        }

        
        
        String startTS = startDate.getRawValue();
        String endTS = endDate.getRawValue();
        
        String startTime1 = startTime.getText();
        if (startTime1 != null && startTime1.length() > 0) {
            startTS += " " + startTime1;
        }
        String endTime1 = endTime.getText();
        if (endTime1 != null && endTime1.length() > 0) {
            endTS += " " + endTime1;
        }
        
        
        if ((endTS != null) && (endTS.length() > 0)) {
            startTS = TimeUtil.normalizeTimestampFormat(startTS, true);
            if (startTS == null)
                return null;
            endTS = TimeUtil.normalizeTimestampFormat(endTS, false);
        }

        query += "<Timestamp start=\"" + startTS + "\"";
        if ((endTS != null) && (endTS.length() > 0)) {
            query += " end=\"" + endTS + "\"";
        }
        query += "/>";
        query += "</Query>";
        
        //System.out.println(query);
        
        return query;
    }

    public GridPanel createTypeGrid() {
        Object[][] data = convertRawDataToObjectGrid();

        // The columns names are not determined until after the data Object[][]
        // has been processed
        RecordDef recordDef = buildRecordDef();

        if (data != null) {
            MemoryProxy proxy = new MemoryProxy(data);

            ArrayReader reader = new ArrayReader(recordDef);
            Store store = new Store(proxy, reader);
            store.load();
            typeGrid.setStore(store);
        }

        ColumnModel columnModel = getColumnModel();

        typeGrid.setColumnModel(columnModel);
        typeGrid.setSelectionModel(cbSelectionModel);
        // typeGrid.setAutoExpandColumn("Type");
        // typeGrid.setFrame(true);

        typeGrid.setStripeRows(true);
        typeGrid.setAutoScroll(true);
        typeGrid.setHeight(125);
        typeGrid.setWidth(150);
        typeGrid.setAutoExpandColumn(1);
        typeGrid.setMargins(5);

        return typeGrid;
    }

    private RecordDef buildRecordDef() {
        FieldDef[] sfd = new StringFieldDef[2];
        sfd[0] = new StringFieldDef("Types");
        sfd[1] = new StringFieldDef("TypeId");

        RecordDef recordDef = new RecordDef(sfd);

        return recordDef;
    }

    private ColumnModel getColumnModel() {
        BaseColumnConfig[] columnConfig;

        columnConfig = new BaseColumnConfig[3];

        columnConfig[0] = new CheckboxColumnConfig(cbSelectionModel);

        ColumnConfig cc1 = new ColumnConfig("Types", "Types", 100);
        columnConfig[1] = cc1;

        ColumnConfig cc2 = new ColumnConfig("TypeId", "TypeId", 100);
        cc2.setHidden(true);
        columnConfig[2] = cc2;

        ColumnModel columnModel = new ColumnModel(columnConfig);

        return columnModel;
    }

    // This converts the incoming data object a HashMap or an ArrayList into a
    // Object[][]
    private Object[][] convertRawDataToObjectGrid() {
        Object[][] displayData = null;

        displayData = new Object[client.typeInfo.types.length][2];
        for (int x = 0; x < client.typeInfo.types.length; x++) {
            displayData[x][0] = client.getTypeName(client.typeInfo.types[x]);
            displayData[x][1] = client.typeInfo.types[x] + "";
        }

        return displayData;
    }

}
